package monitor

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/collectors"
	log "github.com/sirupsen/logrus"
	"qabx.net/common"
	"qabx.net/safe-app-center/pkg/config/constants"
	env "qabx.net/safe-app-center/pkg/config/env"
	"qabx.net/safe-app-center/pkg/utils"
	"strconv"
	"sync"
	"time"
)

var mu sync.Mutex
var Reg *prometheus.Registry

// 统计HeartBeat调用次数
var NumNetflowHeartBeat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	Name: "netflow_heartbeat_numbers",
	Help: "The number of NumNetflowHeartBeat",
}, []string{"deviceId"},
)

// 统计NumNetflow总设备数
var NumNetflowTotal = prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "netflow_total_numbers",
	Help: "The number of NumNetflowTotal",
})

// 统计NumOnlineNetflow
var NumOnlineNetflow = prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "online_netflow_numbers",
	Help: "The number of NumOnlineNetflow",
})

// 统计OnlineNetflow
var OnlineNetflow = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	Name: "online_netflow",
	Help: "The number of Online_netflow",
}, []string{"deviceId"},
)

// 创建 Gauge 用于跟踪当天最新心跳时间
var TodayLastHeartbeat = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	Name: "today_last_heartbeat",
	Help: "Today Last heartbeat time of the gateway in Unix timestamp",
}, []string{"deviceId"},
)

var NetFlowOnlineGateWayNum = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	Name: "netflow_online_gateway_numbers",
	Help: "The number of NetFlowOnlineGateWayNum",
}, []string{"deviceId"},
)

var NetFlowOnlineDeviceNum = prometheus.NewGaugeVec(prometheus.GaugeOpts{
	Name: "netflow_online_device_numbers",
	Help: "The number of NetFlowOnlineDeviceNum",
}, []string{"deviceId"},
)

// 统计NumGetFeatureList次数
var NumGetFeatureList = prometheus.NewCounter(prometheus.CounterOpts{
	Name: "get_feature_list_numbers",
	Help: "The number of GetFeatureList",
})

//// 统计NumPushDeviceOsInfo次数
//var NumPushDeviceOsInfo = prometheus.NewCounter(prometheus.CounterOpts{
//	Name: "push_deviceOs_info_numbers",
//	Help: "The number of PushDeviceOsInfo",
//})

// 统计NumPushTrafficLog次数
var NumPushTrafficLog = prometheus.NewCounter(prometheus.CounterOpts{
	Name: "push_traffic_log_numbers",
	Help: "The number of PushTrafficLog",
})

// 统计NumPushAppAnalyzeLog次数
var NumPushAppAnalyzeLog = prometheus.NewCounter(prometheus.CounterOpts{
	Name: "push_app_analyze_log_numbers",
	Help: "The number of PushAppAnalyzeLog",
})

// 统计NumPushInterceptLog次数
var NumPushInterceptLog = prometheus.NewCounter(prometheus.CounterOpts{
	Name: "push_intercept_log_numbers",
	Help: "The number of PushInterceptLog",
})

// 统计NumUPLoadLeakScanLog次数
var NumUPLoadLeakScanLog = prometheus.NewCounter(prometheus.CounterOpts{
	Name: "push_upload_leak_scan_log_numbers",
	Help: "The number of UPLoadLeakScanLog",
})

func InitMonitorRegister() (registry *prometheus.Registry) {
	// 创建一个自定义的注册表
	registry = prometheus.NewRegistry()

	// 添加 process 和 Go 运行时指标到自定义的注册表中
	registry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
	registry.MustRegister(collectors.NewGoCollector())
	registry.MustRegister(NumNetflowHeartBeat, NumGetFeatureList, NumPushTrafficLog, NumPushAppAnalyzeLog)
	registry.MustRegister(NumPushInterceptLog, NumUPLoadLeakScanLog, NumNetflowTotal, NumOnlineNetflow)
	registry.MustRegister(TodayLastHeartbeat, OnlineNetflow, NetFlowOnlineGateWayNum, NetFlowOnlineDeviceNum)

	NumOnlineNetflow.Set(0)
	NumNetflowTotal.Set(0)
	deviceKey := constants.REDIS_KEY_HEART_BEAT_DEVICE
	deviceList, err := utils.TTLOperator.HGetAll(deviceKey)
	if err != nil {
		log.Panic(err)
	}
	now := time.Now()
	//初始化netflow设备统计数据
	for deviceId, _ := range deviceList {

		NetFlowOnlineDeviceNum.WithLabelValues(deviceId).Set(0)
		NetFlowOnlineGateWayNum.WithLabelValues(deviceId).Set(0)
		NumNetflowHeartBeat.WithLabelValues(deviceId).Set(0)
		//心跳数据初始化
		HeartBeatKey := fmt.Sprintf("%s:%v:%v", constants.REDIS_KEY_HEART_BEAT, now.Format("20060102"), deviceId)
		str, _ := utils.TTLOperator.ZRevRange(HeartBeatKey, 0, 0)
		if len(str) > 0 {
			heartBeat, err := common.StringToFloat64(str[0])
			if err != nil {
				log.Errorf("heartBeat convert error:%v", err)
				TodayLastHeartbeat.WithLabelValues(deviceId).Set(0)
			} else {
				TodayLastHeartbeat.WithLabelValues(deviceId).Set(heartBeat)
			}
			if now.Unix()-int64(heartBeat) > env.Options.NetflowOfflineTime {
				OnlineNetflow.WithLabelValues(deviceId).Set(0)
			} else {
				OnlineNetflow.WithLabelValues(deviceId).Set(1)
			}
		} else {
			TodayLastHeartbeat.WithLabelValues(deviceId).Set(0)
		}

	}
	Reg = registry
	return Reg
}

type ResetCounter struct {
}

// 每日凌晨重置计数器
func (ResetCounter) Run() {
	// 统计NumGetFeatureList次数
	var numGetFeatureList = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "get_feature_list_numbers",
		Help: "The number of GetFeatureList",
	})

	//// 统计NumPushDeviceOsInfo次数
	//var numPushDeviceOsInfo = prometheus.NewCounter(prometheus.CounterOpts{
	//	Name: "push_deviceOs_info_numbers",
	//	Help: "The number of PushDeviceOsInfo",
	//})

	// 统计NumPushTrafficLog次数
	var numPushTrafficLog = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "push_traffic_log_numbers",
		Help: "The number of PushTrafficLog",
	})

	// 统计NumPushAppAnalyzeLog次数
	var numPushAppAnalyzeLog = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "push_app_analyze_log_numbers",
		Help: "The number of PushAppAnalyzeLog",
	})

	// 统计NumPushInterceptLog次数
	var numPushInterceptLog = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "push_intercept_log_numbers",
		Help: "The number of PushInterceptLog",
	})

	// 统计NumUPLoadLeakScanLog次数
	var numUPLoadLeakScanLog = prometheus.NewCounter(prometheus.CounterOpts{
		Name: "push_upload_leak_scan_log_numbers",
		Help: "The number of UPLoadLeakScanLog",
	})

	mu.Lock()
	defer mu.Unlock()
	// 注销旧的计数器
	Reg.Unregister(NumGetFeatureList)
	Reg.Unregister(NumPushTrafficLog)
	Reg.Unregister(NumPushAppAnalyzeLog)
	Reg.Unregister(NumPushInterceptLog)
	Reg.Unregister(NumUPLoadLeakScanLog)

	// 注册新的计数器
	Reg.MustRegister(numGetFeatureList, numPushTrafficLog, numPushAppAnalyzeLog, numPushInterceptLog, numUPLoadLeakScanLog)

	// 更新全局变量
	NumGetFeatureList, NumPushTrafficLog = numGetFeatureList, numPushTrafficLog
	NumPushAppAnalyzeLog, NumPushInterceptLog, NumUPLoadLeakScanLog = numPushAppAnalyzeLog, numPushInterceptLog, numUPLoadLeakScanLog

}

type PrometheusCron struct {
}

type Device struct {
	DeviceId  int64  `json:"deviceId"`
	Mac       string `json:"mac"`
	Ip        string `json:"ip"`
	HeartTime string `json:"HeartTime"`
}

// 定时任务，定时更新netflow心跳数据
func (PrometheusCron) Run() {
	deviceKey := constants.REDIS_KEY_HEART_BEAT_DEVICE
	heartBeatDeviceLen, _ := utils.TTLOperator.HLen(deviceKey)
	NumNetflowTotal.Set(float64(heartBeatDeviceLen))
	//已注册netflow设备列表
	deviceList, err := utils.TTLOperator.HGetAll(deviceKey)

	if err != nil {
		fmt.Println(err)
	}

	now := time.Now()
	nowFormat := now.Format("20060102")
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix()
	redisKeyHeartBeat := constants.REDIS_KEY_HEART_BEAT
	var numOnlineNetflow float64 = 0

	for deviceId, _ := range deviceList {

		key := fmt.Sprintf("%s:%s:%v", redisKeyHeartBeat, nowFormat, deviceId)
		redisHeartBeat, err := utils.TTLOperator.ZRevRangeByScore(key, int32(today), int32(time.Now().Unix()), 1)

		if len(redisHeartBeat) == 0 {
			OnlineNetflow.WithLabelValues(deviceId).Set(0)
			TodayLastHeartbeat.WithLabelValues(deviceId).Set(0)
			continue
		}
		if err != nil {
			log.Errorf("PrometheusCron err:%v", err)
		} else {

			heartBeat, err := strconv.ParseInt(redisHeartBeat[0], 10, 64)
			if err != nil || len(redisHeartBeat) <= 0 {
				OnlineNetflow.WithLabelValues(deviceId).Set(0)
				TodayLastHeartbeat.WithLabelValues(deviceId).Set(0)
			} else {
				if time.Now().Unix()-heartBeat > env.Options.NetflowOfflineTime {
					//设备离线 - 下游gateway和netDevice默认离线
					OnlineNetflow.WithLabelValues(deviceId).Set(0)
					NetFlowOnlineDeviceNum.WithLabelValues(deviceId).Set(0)
					NetFlowOnlineGateWayNum.WithLabelValues(deviceId).Set(0)
				} else {
					//设备在线
					OnlineNetflow.WithLabelValues(deviceId).Set(1)
					numOnlineNetflow = numOnlineNetflow + 1
				}
			}

		}
	}
	NumOnlineNetflow.Set(numOnlineNetflow)
	NumNetflowTotal.Set(float64(len(deviceList)))
}
